package org.kfive.nova.test;

import com.google.common.collect.Lists;

import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * Created by admin on 2017-04-20.
 */
public class StreamExample {

    class Student {

        public Student(long id, String name, int age, int grade, String major, String school) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.grade = grade;
            this.major = major;
            this.school = school;
        }

        /** 学号 */
        private volatile long id;

        private String name;

        private int age;

        /** 年级 */
        private int grade;

        /** 专业 */
        private String major;

        /** 学校 */
        private String school;

        // 省略getter和setter

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public int getGrade() {
            return grade;
        }

        public void setGrade(int grade) {
            this.grade = grade;
        }

        public String getMajor() {
            return major;
        }

        public void setMajor(String major) {
            this.major = major;
        }

        public String getSchool() {
            return school;
        }

        public void setSchool(String school) {
            this.school = school;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    ", grade=" + grade +
                    ", major='" + major + '\'' +
                    ", school='" + school + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        StreamExample example = new StreamExample();
        example.streamCustom();
    }

    public void streamPartition(){
        List<Student> studentList = new ArrayList<Student>(){{
            add(new Student(20160001, "孔明", 20, 1, "土木工程", "武汉大学"));
            add(new Student(20160002, "伯约", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20160003, "玄德", 22, 3, "经济管理", "武汉大学"));
            add(new Student(20160004, "云长", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20161001, "翼德", 21, 2, "机械与自动化", "华中科技大学"));
            add(new Student(20161002, "元直", 23, 4, "土木工程", "华中科技大学"));
            add(new Student(20161003, "奉孝", 23, 4, "计算机科学", "华中科技大学"));
            add(new Student(20162001, "仲谋", 22, 3, "土木工程", "浙江大学"));
            add(new Student(20162002, "鲁肃", 23, 4, "计算机科学", "浙江大学"));
            add(new Student(20163001, "丁奉", 24, 5, "土木工程", "南京大学"));
        }};
        Predicate<Student> predicate = student -> student.getSchool().equals("武汉大学");
        Map<Boolean,List<Student>> partition = studentList.stream().collect(Collectors.partitioningBy(predicate));
        partition.forEach((k,v)-> System.out.println(k+":"+v));
    }

    public void streamGroup(){
        List<Student> studentList = new ArrayList<Student>(){{
            add(new Student(20160001, "孔明", 20, 1, "土木工程", "武汉大学"));
            add(new Student(20160002, "伯约", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20160003, "玄德", 22, 3, "经济管理", "武汉大学"));
            add(new Student(20160004, "云长", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20161001, "翼德", 21, 2, "机械与自动化", "华中科技大学"));
            add(new Student(20161002, "元直", 23, 4, "土木工程", "华中科技大学"));
            add(new Student(20161003, "奉孝", 23, 4, "计算机科学", "华中科技大学"));
            add(new Student(20162001, "仲谋", 22, 3, "土木工程", "浙江大学"));
            add(new Student(20162002, "鲁肃", 23, 4, "计算机科学", "浙江大学"));
            add(new Student(20163001, "丁奉", 24, 5, "土木工程", "南京大学"));
        }};
        Map<String,Long> grouping = studentList.stream().collect(Collectors.groupingBy(Student::getSchool,Collectors.counting()));
        System.out.println(grouping);
    }

    public void streamMax(){
        List<Student> studentList = new ArrayList<Student>(){{
            add(new Student(20160001, "孔明", 20, 1, "土木工程", "武汉大学"));
            add(new Student(20160002, "伯约", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20160003, "玄德", 22, 3, "经济管理", "武汉大学"));
            add(new Student(20160004, "云长", 21, 2, "信息安全", "武汉大学"));
            add(new Student(20161001, "翼德", 21, 2, "机械与自动化", "华中科技大学"));
            add(new Student(20161002, "元直", 23, 4, "土木工程", "华中科技大学"));
            add(new Student(20161003, "奉孝", 23, 4, "计算机科学", "华中科技大学"));
            add(new Student(20162001, "仲谋", 22, 3, "土木工程", "浙江大学"));
            add(new Student(20162002, "鲁肃", 23, 4, "计算机科学", "浙江大学"));
            add(new Student(20163001, "丁奉", 23, 5, "土木工程", "南京大学"));
        }};
        Optional<Student> grouping = studentList.stream().max((p, q)->p.getAge()-q.getAge());
        System.out.println(grouping.get());
    }

    public void streamReduce(){
        List<Integer> sumList = Lists.newArrayList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
//        Integer sum = sumList.stream().collect(Collectors.summingInt((a,b)->a+b));
//        Integer sum = sumList.stream().reduce(10,(o1,o2)->o1+o2);
        List<Integer> sumOther = sumList.stream().collect(Collectors.toCollection(ArrayList::new));
        String sum = sumList.stream().map(a->a.toString()).collect(Collectors.joining(","));

        System.out.println("sum="+sum);
    }

    public void streamFlatMap(){
        List<List<Integer>> lists = new ArrayList<List<Integer>>(){{
            add(Arrays.asList(1,2,3));
            add(Arrays.asList(4,5,6));
            add(Arrays.asList(7,8,9));
        }};
        lists.stream().flatMap(a->a.stream()).forEach(System.out::println);
    }

    public void streamStored(){
        List<Integer> list = Lists.newArrayList(23,45,12,78,65,8,97,444,2111,4266,653);
//        list.stream().limit(5).sorted().collect(Collectors.toList()).forEach(System.out::println);
        list.stream().sorted().limit(5).collect(Collectors.toList()).forEach(System.out::println);
    }

    private class IntegerSupplier implements Supplier{

        @Override
        public Object get() {
            return new Random().nextInt();
        }
    }

    public void streamCustom(){
        Stream.generate(new IntegerSupplier()).limit(10).forEach(System.out::println);
    }
}
